using System;
using System.Collections.Generic;
using System.Text;

namespace CasinoServer.BusinessEntities
{
    public class tmpPokerTable
    {
        private tmpPokerRoomOptions optionsField;

        private tmpCardDeck CardDeckField;

        /// <summary>
        /// Keys are PlayerId's
        /// </summary>
        private Dictionary<int, tmpPokerPlayer> players;

        /// <summary>
        /// Keys are Chair Numbers
        /// </summary>
        private Dictionary<int, tmpPokerChair> chairs;

        private tmpCard FlopCard1Field;
        private tmpCard FlopCard2Field;
        private tmpCard FlopCard3Field;
        private tmpCard RiverCardField;
        private tmpCard TurnCardField;

        public tmpPokerTable(tmpPokerRoomOptions RoomOptions)
        {
            this.optionsField = RoomOptions;
            this.CardDeckField = new tmpCardDeck();
            players = new Dictionary<int, tmpPokerPlayer>();
            chairs = new Dictionary<int, tmpPokerChair>();
                     FlopCard1Field=null;
         FlopCard2Field=null;
         FlopCard3Field=null;
         RiverCardField=null;
         TurnCardField=null;
        }

        public int OwnerJoinTable(int idOwner)
        {
            //earlier appliaction checks if Owner has enaugh money to create his game
            players.Add(idOwner, new tmpPokerPlayer(idOwner, optionsField.EntryMoney,0));
            chairs.Add(0, new tmpPokerChair(0));
            chairs[0].MakeThisDealerChair();
            chairs[0].MakeThisOwnerChair();
            chairs[0].SitDown(idOwner);
            return 0;
        }

        public int JoinTable(int idPlayer)
        {
            if (players.Count == 0)
                throw new tmpPokerException(tmpPokerException.PokerExceptionType.OwnerHasToSitDownFirst);
            if (players.Count == optionsField.MaximumPlayers)
                throw new tmpPokerException(tmpPokerException.PokerExceptionType.ThereAreNoFreeSeats);

            players.Add(idPlayer, new tmpPokerPlayer(idPlayer, optionsField.EntryMoney, chairs.Count));
            chairs.Add(chairs.Count, new tmpPokerChair(chairs.Count));

            chairs[chairs.Count].SitDown(idPlayer);
            return chairs.Count;
        }

        public void LeaveTable(int idPlayer)
        {
            tmpPokerPlayer tmp;
            if (players.TryGetValue(idPlayer, out tmp))
            {
                if (chairs[tmp._ChairId].isTableOwnerChair)
                    throw new tmpPokerException(tmpPokerException.PokerExceptionType.OnwerHasLeftTheTable);
                chairs[tmp._ChairId].StandUp();
                players.Remove(idPlayer);
            }
            else
                throw new tmpPokerException(tmpPokerException.PokerExceptionType.PlayerNotFound);
        }

        public void PlayerGetReady(int idPlayer)
        {
            players[idPlayer].GetReadyToPlay();
        }

        public void StartGame()
        {
            foreach (tmpPokerPlayer player in players.Values)
            {
                if (!player.isReady)
                    throw new Exception("player " + player._PlayerId + " is not ready");
            }
            if (players.Count < optionsField.MaximumPlayers)
                optionsField.MaximumPlayers = players.Count;

            DealCards(0);
        }

        public void NewRound()
        {
            foreach (tmpPokerPlayer player in players.Values)
            {
                player.PrepareForNewRound();
            }

            int dealer=-1;

            for(int chairNr=0;chairNr<chairs.Count;chairNr++)
            {
                if (chairs[chairNr].isDealerChair)
                {
                    dealer = chairNr;
                    break;
                }
            }
            if (dealer == -1)
                throw new tmpPokerException(tmpPokerException.PokerExceptionType.CouldntFindDealer);

            for (int i = 1; i <= chairs.Count; i++)
            {
                if(chairs[(dealer+i)%chairs.Count].isPlaying && !chairs[(dealer+i)%chairs.Count].isDealerChair)
                {
                    chairs[(dealer + i) % chairs.Count].MakeThisDealerChair();
                    chairs[dealer].UnMakeThisDealerChair();
                    DealCards((dealer + i) % chairs.Count);
                    return;
                }
            }

        }


        public void DealCards(int idDealerChair)
        {
            CardDeckField.SortDeck(idDealerChair);

            for (int round = 0; round < 2; round++)
            {
                for (int i = 0; i < chairs.Count; i++)
                {
                    if (chairs[(idDealerChair + i) % chairs.Count].isPlaying && chairs[(idDealerChair + i) % chairs.Count].PlayerId.HasValue)
                    {
                        int player = chairs[(idDealerChair + i) % chairs.Count].PlayerId.Value;
                        players[player].GiveCard(CardDeckField.GetFirst());
                    }
                }
            }
        }

        public void ShowFlop()
        {
            FlopCard1Field = CardDeckField.GetFirst();
            FlopCard2Field = CardDeckField.GetFirst();
            FlopCard3Field = CardDeckField.GetFirst();
        }

        public void ShowTurn()
        {
            TurnCardField = CardDeckField.GetFirst();
        }

        public void ShowRiver()
        {
            RiverCardField = CardDeckField.GetFirst();
        }
    }
}
